package logic

import (
	"context"
	"fmt"
	"googee/service/mqueue/job/internal/svc"
	"time"

	"github.com/LK4D4/trylock"
	"github.com/hibiken/asynq"
	"github.com/zeromicro/go-zero/core/logx"
)

// LeaderBoardSortHandler   shcedule billing to home business
type LeaderBoardClearHandler struct {
	svcCtx     *svc.ServiceContext
	LastUpdate time.Time
	mu         trylock.Mutex
}

func NewLeaderBoardClearHandler(svcCtx *svc.ServiceContext) *LeaderBoardClearHandler {
	return &LeaderBoardClearHandler{
		svcCtx: svcCtx,
	}
}

func (l *LeaderBoardClearHandler) clearDb(ctx context.Context, bid int64, dt time.Time) error {
	//删除leaderboards_buckets
	{
		sql := "DELETE FROM `leaderboards_buckets` WHERE bid=? and create_time<=?"
		result, err := l.svcCtx.SqlConn.ExecCtx(ctx, sql, bid, dt.Format("2006-01-02"))
		if err != nil {
			logx.Error(err)
		}

		if n, err := result.RowsAffected(); err == nil {
			logx.Infof("删除leaderboards_buckets数据%v条", n)
		}
	}

	//删除leaderboards_data
	{
		sql := "DELETE FROM `leaderboards_data` WHERE bid=? and create_time<=?"
		result, err := l.svcCtx.SqlConn.ExecCtx(ctx, sql, bid, dt.Format("2006-01-02"))
		if err != nil {
			logx.Error(err)
		}

		if n, err := result.RowsAffected(); err == nil {
			logx.Infof("删除leaderboards_data数据%v条", n)
		}
	}

	return nil
}

//  every one minute exec : if return err != nil , asynq will retry
func (l *LeaderBoardClearHandler) ProcessTask(ctx context.Context, _ *asynq.Task) error {

	fmt.Printf("shcedule  clear job  -----> every one minute exec ,time:%v ,l=%v\n", time.Now().Unix(), l)
	d := time.Since(l.LastUpdate)

	if l.mu.TryLock() {
		defer l.mu.Unlock()
		l.LastUpdate = time.Now()
		//计算周期不能太密集,暂时是1分钟对应移动一下桶里面的数据
		if d.Seconds() < 50 {
			return nil
		}

		//清空过期数据
		//获得所有的排行榜
		boards, err := l.svcCtx.LeaderboardsModel.FindAll(ctx)
		if err != nil {
			return nil
		}

		now := time.Now()
		for _, b := range boards {
			if b.ValidDays > 0 {
				addTime := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
				dt := addTime.AddDate(0, 0, -int(b.ValidDays))
				err := l.clearDb(ctx, b.Id, dt)
				if err != nil {
					logx.Error(err)
				}
			}
		}
	}

	return nil
}
